package com.lanchetech.admin.service.impl;


import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.util.CollectionUtils;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.lanchetech.admin.config.WeChatPayProperties;
import com.lanchetech.admin.service.*;
import com.lanchetech.bean.request.*;
import com.lanchetech.bean.response.*;
import com.lanchetech.bean.util.PageHelpUtil;
import com.lanchetech.bean.vo.*;
import com.lanchetech.common.enums.*;
import com.lanchetech.common.exception.ResultCodeException;
import com.lanchetech.dao.*;
import com.lanchetech.entity.*;
import com.lanchetech.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.lanchetech.common.constants.JypConstant.HIPO_ADMIN_ID;


@Service
public class UserServiceImpl implements UserService {
    private final Logger log = LoggerFactory.getLogger(this.getClass());


    @Autowired
    UserMapper userMapper;

    @Autowired
    AdminService adminService;

    @Autowired
    WithdrawMapper withdrawMapper;

    @Autowired
    WxPayService wxPayService;

    @Autowired
    private WeChatPayProperties properties;

    @Autowired
    UserRelationshipMapper userRelationshipMapper;

    @Autowired
    InviteCodeService inviteCodeService;

    @Autowired
    UserInfoMapper userInfoMapper;

    @Autowired
    UserCommissionMapper userCommissionMapper;

    @Autowired
    PrivilegeMapper privilegeMapper;

    @Autowired
    ShopApplyMapper shopApplyMapper;

    @Autowired
    ShopMapper shopMapper;

    // 环境变量
    @Value("${env}")
    private String env;

    @Autowired
    DaoService daoService;

    @Autowired
    BalanceFlowMapper balanceFlowMapper;

    @Autowired
    UserGroupMapper userGroupMapper;

    @Autowired
    GroupService groupService;

    @Autowired
    CardFlowMapper cardFlowMapper;

    @Autowired
    InformationMapper informationMapper;

    @Autowired
    IdentityMapper identityMapper;

    @Autowired
    AdFlowMapper adFlowMapper;

    @Autowired
    RewardQueueMapper rewardQueueMapper;

    @Autowired
    UserAgentLevelMapper userAgentLevelMapper;

    @Autowired
    InvoiceService invoiceService;

    @Autowired
    InvoiceApplyMapper invoiceApplyMapper;

    @Autowired
    ShopRelationshipMapper shopRelationshipMapper;

    @Autowired
    BonusCountMapper bonusCountMapper;

    @Autowired
    ShopService shopService;

    @Autowired
    ShopStatisticsMapper shopStatisticsMapper;

    @Autowired
    RankRecordMapper rankRecordMapper;

    @Autowired
    TicketMapper ticketMapper;

    @Autowired
    FundService fundService;

    @Autowired
    UserService userService;

    @Autowired
    TenantMapper tenantMapper;

    @Autowired
    TenantFlowMapper tenantFlowMapper;

    @Autowired
    AreaApplyMapper areaApplyMapper;

    @Autowired
    AreaApplyDetailMapper areaApplyDetailMapper;

    @Autowired
    AreaMapper areaMapper;

    @Autowired
    SuggestionMapper suggestionMapper;

    @Autowired
    AnnouncementMapper announcementMapper;

    @Autowired
    ShopAnnouncementMapper shopAnnouncementMapper;

    @Autowired
    JpushService jpushService;

    @Autowired
    CurrentIdentityMapper currentIdentityMapper;

    @Autowired
    AnnouncementService announcementService;

    @Autowired
    KuaidizsService kuaidizsService;

    @Autowired
    BossRelationshipMapper bossRelationshipMapper;

    @Autowired
    BossInviteShopMapper bossInviteShopMapper;

    @Autowired
    BossIdentityMapper bossIdentityMapper;

    @Autowired
    LevelService levelService;

    @Autowired
    GiveIdentityRecordMapper giveIdentityRecordMapper;

    @Autowired
    BankAccountMapper bankAccountMapper;

    @Autowired
    DividendPrecipitationMapper dividendPrecipitationMapper;

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    MsgUserMapper msgUserMapper;

    @Autowired
    MsgMapper msgMapper;

    @Autowired
    GroupsPerformanceMapper groupsPerformanceMapper;

    @Autowired
    ShareholderPerformanceMapper shareholderPerformanceMapper;

    @Autowired
    WelfareFlowMapper welfareFlowMapper;

    @Autowired
    VipService vipService;

    @Autowired
    private UserCelebrityMapper userCelebrityMapper;

    @Override
    public ResultData<UserDetailResp> getUserDetail(Long id) {
        UserDetailResp user = userMapper.findOneById(id);
        UserInfo userInfo = userInfoMapper.findOneByUserId(id);
        user.setProvince(userInfo.getProvince());
        user.setCity(userInfo.getCity());
        user.setGender(userInfo.getGender());
        user.setInviteCode(inviteCodeService.generateInviteCode(id));
        user.setRealName(userInfo.getRealName());
        user.setIdCard(userInfo.getIdCard());
        List<Privilege> privilegeList = privilegeMapper.findAllByUserId(id);
        user.setPrivilegeList(privilegeList);
        CurrentIdentity currentIdentity = currentIdentityMapper.findOneByUserId(user.getId());
        if (currentIdentity != null) {
            user.setCurrentIdentity(currentIdentity.getAllIdentityType());
        }
        user.setIdentity(identityMapper.findOneByUserId(user.getId()));
        user.setIsBoss(bossIdentityMapper.findOneByUserId(user.getId()) != null);
        return new ResultData<>(user);
    }

    @Override
    public BaseResp modifyUserInfo(UserInfo userInfo) {
        userInfo.setUpdatedAt(new Date());
        userInfoMapper.updateIdCardAndRealNameAndUpdatedAtByUserId(userInfo);
        return new BaseResp();
    }

    @Override
    public BaseResp blockUser(Long id, Integer status) {
        userMapper.updateStatusById(status, id);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<User>> getUserPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<User> list = userMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp createUserPrivilege(Privilege privilege) {
        privilege.setCreatedAt(new Date());
        privilegeMapper.insert(privilege);
        return new BaseResp();
    }

    @Override
    public BaseResp deleteUserPrivilege(Long id) {
        privilegeMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<WithdrawResp>> getWithdrawPage(WithdrawReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<WithdrawResp> list = withdrawMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public void exportWithdrawExcel(WithdrawReq req, HttpServletResponse response) throws IOException {
        String fileName = new String(("提现记录列表导出数据.xlsx").getBytes(), "UTF-8");
        List<WithdrawResp> list = withdrawMapper.findAllPage(req);
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        EasyExcel.write(response.getOutputStream(), WithdrawResp.class).sheet("提现记录列表导出数据").doWrite(list);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public BaseResp checkWithdraw(Withdraw req) {
        Withdraw withdraw = withdrawMapper.selectByPrimaryKey(req.getId());
        // 提现中的，才能审核
        if (WithdrawStatusEnum.PROCESSING.getStatus().equals(withdraw.getStatus())) {
            // 提现成功
            if (WithdrawStatusEnum.SUCCESS.getStatus().equals(req.getStatus())) {
                // 提现前一定要检查余额
                User user = userMapper.selectByPrimaryKey(withdraw.getUserId());
                if (user.getPoint().compareTo(withdraw.getAmount()) >= 0) {
                    if (WithdrawTypeEnum.WECHAT.getPayway().equals(withdraw.getType())) {
                        // 微信提现请求
                        return this.withdrawToWechat(withdraw, user, "116.62.4.239");
                    } else {
                        // 银行卡和支付宝提现请求
                        return this.withdrawToAlipay(withdraw, user);
                    }
                } else {
                    return new BaseResp(ResultCode.INSUFFICIENT_BALANCE);
                }
            } else {
                User user = userMapper.selectByPrimaryKey(withdraw.getUserId());
                withdraw.setRemainingAmount(user.getPoint());
                withdraw.setStatus(WithdrawStatusEnum.REFUSE.getStatus());
                withdraw.setUpdatedAt(new Date());
                withdrawMapper.updateByPrimaryKey(withdraw);

                return new BaseResp();
            }
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
    }

    @Override
    public ResultData<BasePageResp<RelationshipResp>> getUserRelationshipPage(RelationshipReq req) {
        if (!StringUtils.isEmpty(req.getSubordinatePhone())) {
            User subordinate = userMapper.findOneByUsername(req.getSubordinatePhone());
            req.setSubordinateId(subordinate == null ? 0L : subordinate.getId());
        }
        if (!StringUtils.isEmpty(req.getSuperiorPhone())) {
            User superior = userMapper.findOneByUsername(req.getSuperiorPhone());
            req.setSuperiorId(superior == null ? 0L : superior.getId());
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<RelationshipResp> list = userRelationshipMapper.findAllPage(req);

        if (CollectionUtils.isEmpty(list)) {
            return PageHelpUtil.buildPage(list, page);
        }

        List<Long> userIds = new ArrayList<>();
        list.stream().forEach(item -> {
            if (!userIds.contains(item.getSuperiorId())) {
                userIds.add(item.getSuperiorId());
            }
            if (!userIds.contains(item.getSubordinateId())) {
                userIds.add(item.getSubordinateId());
            }
        });
        Map<Long, User> userMap = daoService.getUserMap(userIds);
        list.stream().forEach(item -> {
            item.setSuperiorAvatar(userMap.get(item.getSuperiorId()).getAvatar());
            item.setSuperiorNickname(userMap.get(item.getSuperiorId()).getNickname());
            item.setSuperiorPhone(userMap.get(item.getSuperiorId()).getUsername());
            item.setSuperiorLevel(userMap.get(item.getSuperiorId()).getLevel());

            item.setSubordinateNickname(userMap.get(item.getSubordinateId()).getNickname());
            item.setSubordinateAvatar(userMap.get(item.getSubordinateId()).getAvatar());
            item.setSubordinatePhone(userMap.get(item.getSubordinateId()).getUsername());
            item.setSubordinateLevel(userMap.get(item.getSubordinateId()).getLevel());
        });

        return PageHelpUtil.buildPage(list, page);
    }

    /**
     * 提现到微信零钱
     *
     * @param withdraw
     */
    private BaseResp withdrawToWechat(Withdraw withdraw, User user, String ip) {
        WxPayService payService = wxPayService;
        // 进行微信提现
        // 执行提现, 用户的余额在外部做检查，在这里已经默认余额充足
        Date nowTime = new Date(System.currentTimeMillis());
        SimpleDateFormat sdFormatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        //订单号由用户操作时间毫秒数+用户id实现的
        String outBizNo = sdFormatter.format(nowTime) + user.getId();
        EntPayRequest entPayRequest = EntPayRequest.newBuilder()
                .amount(withdraw.getAmount().multiply(new BigDecimal(100)).intValue())
                .mchAppid(this.properties.getAppId())
                .description("小嗨提现")
                .mchId(this.properties.getMchId())
                .openid(user.getOpenid())
                .checkName("NO_CHECK")
                .partnerTradeNo(outBizNo)
                .spbillCreateIp(ip)
                .build();

        EntPayResult entPayResult = null;
        // 只有生产环境能真实提现，其他环境，直接按提现成功处理，但不给钱。
        if ("production".equals(env)) {
            try {
                entPayResult = payService.getEntPayService().entPay(entPayRequest);
                log.info("微信提现到零钱成功：{}", entPayResult);
            } catch (WxPayException e) {
                log.error("微信提现到零钱失败：{}", e);
                return new BaseResp(ResultCode.FAIL);
            }
        }

        userMapper.updatePointById(user.getPoint().subtract(withdraw.getAmount()), user.getId());

        // 创建资金流水
        balanceFlowMapper.insert(BalanceFlow.builder()
                .userId(user.getId())
                .amount(withdraw.getAmount())
                .tradeType(TradeTypeEnum.WITHDRAW.getTradeType())
                .type(TradeTypeEnum.WITHDRAW.getType())
                .point(user.getPoint().subtract(withdraw.getAmount()))
                .relateId(withdraw.getId())
                .remark("提现")
                .createdAt(new Date())
                .build());

        withdraw.setRemainingAmount(user.getPoint().subtract(withdraw.getAmount()));
        withdraw.setAccount(user.getOpenid());
        withdraw.setType(WithdrawTypeEnum.WECHAT.getPayway());
        withdraw.setStatus(WithdrawStatusEnum.SUCCESS.getStatus());
        withdraw.setUpdatedAt(nowTime);
        withdrawMapper.updateByPrimaryKey(withdraw);
        return new BaseResp();
    }

    /**
     * 提现到支付宝
     * 实现是财务线下打款，打款后点击确认，完成提现
     *
     * @param withdraw
     */
    private BaseResp withdrawToAlipay(Withdraw withdraw, User user) {
        userMapper.updatePointById(user.getPoint().subtract(withdraw.getAmount()), user.getId());

        // 创建资金流水
        balanceFlowMapper.insert(BalanceFlow.builder()
                .userId(user.getId())
                .amount(withdraw.getAmount())
                .tradeType(TradeTypeEnum.WITHDRAW.getTradeType())
                .type(TradeTypeEnum.WITHDRAW.getType())
                .point(user.getPoint().subtract(withdraw.getAmount()))
                .relateId(withdraw.getId())
                .remark("提现")
                .createdAt(new Date())
                .build());

        withdraw.setRemainingAmount(user.getPoint().subtract(withdraw.getAmount()));
        withdraw.setStatus(WithdrawStatusEnum.SUCCESS.getStatus());
        withdraw.setUpdatedAt(new Date());
        withdrawMapper.updateByPrimaryKey(withdraw);

        return new BaseResp();
    }

    @Override
    public void exportUserExcel(PageReq req, HttpServletResponse response) throws IOException {
        String fileName = new String(("用户列表导出数据.xlsx").getBytes(), "UTF-8");
        List<User> list = userMapper.findAllPage(req);
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);
        EasyExcel.write(response.getOutputStream(), UserDetailResp.class).sheet("用户列表导出数据").doWrite(list);
    }

    @Override
    public ResultData<BasePageResp<UserCommissionResp>> getUserCommissionPage(UserCommissionReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<UserCommissionResp> list = userCommissionMapper.findAllPage(req);
        if (CollectionUtils.isEmpty(list)) {
            return PageHelpUtil.buildPage(list, page);
        }
        List<Long> userIds = new ArrayList<>();
        list.stream().forEach(item -> {
            if (!userIds.contains(item.getSuperiorId())) {
                userIds.add(item.getSuperiorId());
            }
            if (!userIds.contains(item.getSubordinateId())) {
                userIds.add(item.getSubordinateId());
            }
        });

        Map<Long, User> userMap = daoService.getUserMap(userIds);

        list.stream().forEach(item -> {
            item.setSuperiorNickname(userMap.get(item.getSuperiorId()).getNickname());
            item.setSuperiorAvatar(userMap.get(item.getSuperiorId()).getAvatar());
            item.setSuperiorLevel(userMap.get(item.getSuperiorId()).getLevel());

            item.setSubordinateNickname(userMap.get(item.getSubordinateId()).getNickname());
            item.setSubordinateAvatar(userMap.get(item.getSubordinateId()).getAvatar());
            item.setSubordinateLevel(userMap.get(item.getSubordinateId()).getLevel());
        });

        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp issueConsumeCommission(UserCommission userCommission) {
        userCommission.setType(UserCommissionTypeEnum.CONSUME.getType());

        // 设置冻结时间
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DATE, 14);

        userCommission.setFreezeTime(calendar.getTime());
        userCommission.setStatus(UserCommissionStatusEnum.FREEZE.getStatus());
        userCommission.setCreatedAt(now);
        userCommission.setUpdatedAt(now);
        userCommission.setAmount(userCommission.getAmount());

        Identity identity = identityMapper.findOneByUserId(userCommission.getSuperiorId());

        userCommission.setIdentityType(identity == null ? (byte) -1 : identity.getType());
        userCommission.setBusinessType(UserCommissionBusinessTypeEnum.USER.getType());
        userCommissionMapper.insert(userCommission);
        return new BaseResp();
    }

    @Override
    public BaseResp cancelCommission(Long id) {
        UserCommission commission = userCommissionMapper.selectByPrimaryKey(id);
        // 只有冻结中的佣金可以被扣除（无论是否解冻）
        if (commission.getStatus().equals(UserCommissionStatusEnum.FREEZE.getStatus())) {
            commission.setStatus(UserCommissionStatusEnum.MANAGER.getStatus());
            commission.setUpdatedAt(new Date());
            userCommissionMapper.updateByPrimaryKey(commission);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<BalanceFlowVO>> getBalanceFlowPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<BalanceFlow> list = balanceFlowMapper.findAllPage(req);
        List<BalanceFlowVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(BalanceFlow::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                BalanceFlowVO vo = new BalanceFlowVO();
                BeanUtils.copyProperties(item, vo);
                vo.setNickname(userMap.get(item.getUserId()).getNickname());
                result.add(vo);
            });
        }
        return PageHelpUtil.buildPage(result, page);
    }

    @Override
    public BaseResp createUserRelationship(Long userId, String phone) {
        User sub = userMapper.findOneByUsername(phone);
        if (sub == null) {
            return new BaseResp(ResultCode.USER_NOT_EXISTS);
        }
        UserRelationship ship = userRelationshipMapper.findOneBySubordinateId(sub.getId());
        if (ship != null) {
            userRelationshipMapper.deleteByPrimaryKey(ship.getId());
        }
        UserRelationship ship2 = userRelationshipMapper.findOneBySuperiorIdAndSubordinateId(sub.getId(), userId);
        if (ship2 != null) {
            return new BaseResp(ResultCode.RELATIONSHIP_CONFLICT);
        }
        UserRelationship userRelationship = new UserRelationship();
        userRelationship.setSuperiorId(userId);
        userRelationship.setSubordinateId(sub.getId());
        userRelationship.setCreatedAt(new Date());
        userRelationship.setUpdatedAt(new Date());
        userRelationship.setStatus(RelationshipStatusEnum.BIND.getStatus());

        Identity identity = identityMapper.findOneByUserId(userId);
        userRelationship.setType(identity == null ? (byte) -1 : identity.getType());
        userRelationship.setSubordinateLevel(sub.getLevel());

        userRelationshipMapper.insert(userRelationship);

        if (identity != null && sub.getLevel() > UserLevelEnum.CUSTOMER.getLevel()) {
            userGroupMapper.deleteByMemberId(sub.getId());
            groupService.createUserGroup(identity.getUserId(), sub);
        }

        return new BaseResp();
    }

    @Override
    public BaseResp lockUserRelationship(Long userId) {
        UserRelationship ship = userRelationshipMapper.findOneBySubordinateId(userId);
        if (ship != null) {
            ship.setStatus(RelationshipStatusEnum.BIND.getStatus());
            ship.setUpdatedAt(new Date());
            userRelationshipMapper.updateByPrimaryKeySelective(ship);
        } else {
            return new BaseResp(ResultCode.NOT_HAVE_RELATIONSHIP);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<UserGroupVO>> getUserGroupPage(UserGroupReq req) {

        if (!StringUtils.isEmpty(req.getCaptainPhone())) {
            User captain = userMapper.findOneByUsername(req.getCaptainPhone());
            req.setCaptainId(captain != null ? captain.getId() : 0L);
        }

        if (!StringUtils.isEmpty(req.getMemberPhone())) {
            User member = userMapper.findOneByUsername(req.getMemberPhone());
            req.setMemberId(member != null ? member.getId() : 0L);
        }

        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<UserGroupVO> list = userGroupMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {

            List<Long> userIds = new ArrayList<>();
            list.stream().forEach(item -> {
                userIds.add(item.getCaptainId());
                userIds.add(item.getMemberId());
            });

            Map<Long, User> userMap = daoService.getUserMap(userIds);
            list.stream().forEach(item -> {
                item.setCaptainAvatar(userMap.get(item.getCaptainId()).getAvatar());
                item.setCaptainNickname(userMap.get(item.getCaptainId()).getNickname());
                item.setMemberAvatar(userMap.get(item.getMemberId()).getAvatar());
                item.setMemberNickname(userMap.get(item.getMemberId()).getNickname());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp deleteUserGroup(Long id) {
        userGroupMapper.deleteByPrimaryKey(id);
        return new BaseResp();
    }

    @Override
    public BaseResp changeCaptain(Long id, Long captainId) {

        UserGroup userGroup = userGroupMapper.selectByPrimaryKey(id);

        if (!userGroup.getCaptainId().equals(captainId)) {
            // 不能已经是团员的团长
            UserGroup result = userGroupMapper.findOneByCaptainIdAndMemberId(captainId, userGroup.getMemberId());
            if (result != null) {
                return new BaseResp(ResultCode.ALREADY_CAPTAIN);
            }

            // 不能是团员的团员
            UserGroup result2 = userGroupMapper.findOneByCaptainIdAndMemberId(userGroup.getMemberId(), captainId);
            if (result2 != null) {
                return new BaseResp(ResultCode.ALREADY_MEMBER);
            }

            User captain = userMapper.selectByPrimaryKey(captainId);

            if (captain == null) {
                return new BaseResp(ResultCode.ACCT_NOT_EXIST);
            }

            userGroup.setCaptainId(captainId);
            userGroup.setCaptainLevel(captain.getLevel());
            userGroup.setUpdatedAt(new Date());
            userGroupMapper.updateByPrimaryKeySelective(userGroup);
        }

        return new BaseResp();
    }

    @Override
    public ResultData<TransferUserGroupVO> transferCaptain(Long oldCaptainId, Long newCaptainId) {
        ResultData resultData = new ResultData();

        TransferUserGroupVO vo = new TransferUserGroupVO();
        // 获取老团长的所有团员
        List<UserGroup> userGroupList = userGroupMapper.findAllByCaptainId(oldCaptainId);

        if (CollectionUtils.isEmpty(userGroupList)) {
            resultData.setResultCode(ResultCode.NO_MEMBER);
            return resultData;
        }

        vo.setTotal(Long.valueOf(userGroupList.size()));
        vo.setSuccess(0L);

        User newCaptain = userMapper.selectByPrimaryKey(newCaptainId);

        if (newCaptain == null) {
            resultData.setResultCode(ResultCode.ACCT_NOT_EXIST);
            return resultData;
        }

        // 逐条变更团长，有问题的就跳过
        userGroupList.stream().forEach(item -> {
            // 不能已经是团员的团长
            UserGroup result = userGroupMapper.findOneByCaptainIdAndMemberId(newCaptainId, item.getMemberId());
            if (result == null) {

                // 不能是团员的团员
                UserGroup result2 = userGroupMapper.findOneByCaptainIdAndMemberId(item.getMemberId(), newCaptainId);

                if (result2 == null) {
                    vo.setSuccess(vo.getSuccess() + 1);

                    item.setCaptainId(newCaptainId);
                    item.setCaptainLevel(newCaptain.getLevel());
                    item.setUpdatedAt(new Date());
                    userGroupMapper.updateByPrimaryKeySelective(item);
                }
            }
        });

        return new ResultData<>(vo);
    }

    @Override
    public BaseResp updateCardPoint(Long userId, BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            return new BaseResp();
        }
        BigDecimal cardPoint = userMapper.selectByPrimaryKey(userId).getCardPoint().add(amount);
        userMapper.updateCardPointById(cardPoint, userId);

        // 创建消费记录
        cardFlowMapper.insert(CardFlow.builder()
                .userId(userId)
                .amount(amount)
                .tradeType(amount.compareTo(BigDecimal.ZERO) > 0 ? CardTradeTypeEnum.SYSTEM_GIVING.getTradeType() : CardTradeTypeEnum.SYSTEM_DEDUCT.getTradeType())
                .type(amount.compareTo(BigDecimal.ZERO) > 0 ? CardTradeTypeEnum.SYSTEM_GIVING.getType() : CardTradeTypeEnum.SYSTEM_DEDUCT.getType())
                .cardPoint(cardPoint)
                .remark("")
                .createdAt(new Date())
                .build());
        return new BaseResp();
    }

    @Override
    public BaseResp editShopApply(ShopApply shopApply) {
        ShopApply old = shopApplyMapper.findOneByUserIdAndDeleted(shopApply.getUserId(), DeletedEnum.DEFAULT.getStatus());
        if (shopApply.getId() == null && old == null) {
            shopApply.setDeleted(DeletedEnum.DEFAULT.getStatus());
            shopApply.setCreatedAt(new Date());
            shopApply.setUpdatedAt(new Date());
            if (shopApply.getKind() == null) {
                shopApply.setKind(ShopKindEnum.PROJECT.getKind());
            }
            shopApplyMapper.insert(shopApply);
        } else if (old != null) {
            shopApply.setUpdatedAt(new Date());
            shopApplyMapper.updateByPrimaryKey(shopApply);
        } else {
            return new BaseResp(ResultCode.FAIL);
        }
        return new BaseResp();
    }


    @Override
    public ResultData<BasePageResp<ShopApplyVO>> getShopApplyPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ShopApplyVO> list = shopApplyMapper.findAllPage(req);
        if (!list.isEmpty()) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(ShopApplyVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                if (item.getUserId() != null) {
                    item.setUserNickname(userMap.get(item.getUserId()).getNickname());
//                    item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                }
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp deleteShopApply(Long id) {
        shopApplyMapper.updateDeletedById(DeletedEnum.DEFAULT.getStatus(), id);
        return new BaseResp();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResp auditShopApply(ShopApply req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        ShopApply shopApply = shopApplyMapper.selectByPrimaryKey(req.getId());

        if (ShopApplyAuditEnum.TO_AUDIT.getStatus().equals(shopApply.getAuditStatus())) {
            if (ShopApplyAuditEnum.PASS.getStatus().equals(req.getAuditStatus())) {

                // 1 后台管理  2 小程序
                if (shopApply.getApplyType() == 1) {
                    Shop shop = getShop(shopApply);
                    shopApply.setAuditStatus((byte) 1);
                    // 修改审核状态
                    shopApplyMapper.updateByPrimaryKeySelective(shopApply);
                    shopApply.setCount(0);
                    shopApplyMapper.updateCount(shopApply.getId(), shopApply.getCount());
                    return shopService.applyShop(shop);
                }

                Shop shop = getShop(shopApply);
                if (shopApply.getShopId() == null) {
                    if (shop.getKind() == null) {
                        shop.setKind(ShopKindEnum.PROJECT.getKind());
                    }
                    BigDecimal bigDecimal = new BigDecimal("5");
                    // 如果没店，则创建
                    shop.setType(shopApply.getShopType());
                    shop.setOverallStar(bigDecimal);
                    shop.setServiceStar(bigDecimal);
                    shop.setEnvironmentStar(bigDecimal);
                    shop.setValueStar(bigDecimal);
                    shop.setPermitImage(shopApply.getPermitImage());
                    // 默认抽成0.1
                    shop.setServiceRate(daoService.getHipoConfigNumber(HipoConfigEnum.SERVICE_RATE.getConfig()));
                    shop.setShopLevel(ShopLevelEnum.SUPERIOR_PRODUCT_SHOP.getLevel());
                    shopMapper.insert(shop);
                    shopApply.setShopId(shop.getId());

                    //首次登陆快递助手获取mallUserId
//                    if(ShopTypeEnum.PRODUCER.getType().equals(shop.getType())){
//                        kuaidizsService.getLoginUrl(shop);
//                    }


                    //新建商店统计数据
                    shopStatisticsMapper.insert(ShopStatistics.builder()
                            .shopId(shop.getId())
                            .orderAmount(BigDecimal.ZERO)
                            .orderCount(0L)
                            .customCount(0L)
                            .visitCount(0L)
                            .viewCount(0L)
                            .createdAt(new Date())
                            .updatedAt(new Date())
                            .build());

                    shopService.createTenant(shop);

                    userMapper.updateShopIdById(shop.getId(), shopApply.getUserId());

                    // 将老板推荐关系绑定
                    BossRelationship bossRelationship = bossRelationshipMapper.findOneBySubordinateId(shopApply.getUserId());
                    if (bossRelationship != null && RelationshipStatusEnum.NOT_BIND.getStatus().equals(bossRelationship.getStatus())) {
                        // 将绑定设置为已绑定，并同时增加他的下级数量
                        bossRelationship.setStatus(RelationshipStatusEnum.BIND.getStatus());
                        bossRelationshipMapper.updateByPrimaryKeySelective(bossRelationship);

                        // 增加邀请数量
                        BossIdentity bossIdentity = bossIdentityMapper.findOneByUserId(bossRelationship.getSuperiorId());

                        if (bossIdentity != null) {
                            bossIdentity.setBossL1Number(bossIdentity.getBossL1Number() + 1);
                            levelService.isBossPromotion(bossIdentity);

                            // 创建老板邀请的商家
                            bossInviteShopMapper.insert(BossInviteShop.builder()
                                    .userId(bossRelationship.getSuperiorId())
                                    .shopId(shop.getId())
                                    .performance(BigDecimal.ZERO)
                                    .commission(BigDecimal.ZERO)
                                    .createdAt(new Date())
                                    .updatedAt(new Date())
                                    .build());
                        }
                    }

                    // 创建推荐商家
                    UserRelationship userRelationship = userRelationshipMapper.findOneBySubordinateId(shop.getUserId());
                    if (userRelationship != null) {
                        Identity identity = identityMapper.findOneByUserId(userRelationship.getSuperiorId());
                        // 合伙人和董事，邀请下级（无论是强绑定还是弱绑定关系），只要在此期间，申请注册商家。则视为推荐商家。
                        if (identity != null && (identity.getType().equals(IdentityTypeEnum.PARTNER.getType()) || identity.getType().equals(IdentityTypeEnum.SHAREHOLDER.getType()))) {
                            shopRelationshipMapper.insert(ShopRelationship.builder()
                                    .userId(userRelationship.getSuperiorId())
                                    .shopId(shop.getId())
                                    .createdAt(new Date())
                                    .build());
                        }
                    }
                } else {
                    // 如果有店，则更新
                    shop.setId(shopApply.getShopId());
                    shopMapper.updateByPrimaryKeySelective(shop);
                }

                //发送商家认证通知
                announcementService.sendShopAnnouncement(shop);
            }

            shopApply.setAuditAdmin(String.valueOf(admin.getId()));
            shopApply.setAuditMessage(req.getAuditMessage());
            shopApply.setAuditStatus(req.getAuditStatus());
            shopApply.setAuditTime(new Date());
            shopApply.setUpdatedAt(new Date());
            shopApplyMapper.updateByPrimaryKeySelective(req);
        }
        shopApply.setCount(0);
        shopApplyMapper.updateCount(shopApply.getId(), shopApply.getCount());

        return new BaseResp();
    }

    private static Shop getShop(ShopApply shopApply) {
        Shop shop = Shop.builder()
                .shopName(shopApply.getTenantName())
                .avatar(shopApply.getFrontImage())
                .mainImage(shopApply.getFrontImage())
                .imageList(shopApply.getEnvironmentImage())
                .province(shopApply.getProvince())
                .city(shopApply.getCity())
                .area(shopApply.getArea())
                .mergerName(shopApply.getMergerName())
                .phone(shopApply.getPhone())
                .name(shopApply.getName())
                .address((StringUtils.isEmpty(shopApply.getLocation()) ? "" : shopApply.getLocation()) + (StringUtils.isEmpty(shopApply.getAddress()) ? "" : shopApply.getAddress()))
                .longitude(shopApply.getLongitude())
                .latitude(shopApply.getLatitude())
                .createdAt(new Date())
                .updatedAt(new Date())
                .status(ToggleEnum.ON.getStatus())
                .userId(shopApply.getUserId())
                .businessStart(shopApply.getBusinessStart())
                .businessEnd(shopApply.getBusinessEnd())
                .industryFirstId(shopApply.getIndustryFirstId())
                .industrySecondId(shopApply.getIndustrySecondId())
                .industryName(shopApply.getIndustryName())
                .type(shopApply.getShopType())
                .deleted(DeletedEnum.DEFAULT.getStatus())
                .account(shopApply.getAccount())
                .bank(shopApply.getBank())
                .openBank(shopApply.getOpenBank())
                .openName(shopApply.getOpenName())
                .idCardBack(shopApply.getIdCardBack())
                .idCardName(shopApply.getIdCardName())
                .idCardNumber(shopApply.getIdCardNumber())
                .kind(shopApply.getKind())
                .province(shopApply.getProvince())
                .area(shopApply.getArea())
                .environmentImage(shopApply.getEnvironmentImage())
                .certificateType(shopApply.getCertificateType())
                .licenseLongTerm(shopApply.getLicenseLongTerm())
                .licenseValidTime(shopApply.getLicenseValidTime())
                .licenseNumber(shopApply.getLicenseNumber())
                .verifyStatus(true)
                .logo(shopApply.getLogo())
                .licenseImage(shopApply.getLicenseImage())
                .idCardPositive(shopApply.getIdCardPositive())
                .permitImage(shopApply.getPermitImage())
                .shopLevel(shopApply.getShopLevel())
                .idCardCode(shopApply.getIdCardNumber())
                .certificateType(shopApply.getCertificateType())
                .industryName(shopApply.getIndustryName())
                .shopLevel(shopApply.getShopLevel())
                .certificateType(shopApply.getCertificateType())
//                .shopOpenTime(shopApply.getShopOpenTime())
                .build();
        return shop;
    }

    @Override
    public BaseResp getInformationPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<Information> list = informationMapper.findAllPage(req);
        return PageHelpUtil.buildPage(list, page);

    }

    @Override
    public BaseResp updateAdPoint(Long userId, BigDecimal amount, Byte tradeType) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            return new BaseResp();
        }
        User user = userMapper.selectByPrimaryKey(userId);
        BigDecimal adPoint;
        Byte type;
        if (AdFlowTradeTypeEnum.SYSTEM_DEDUCT.getTradeType().equals(tradeType)) {
            adPoint = user.getAdPoint().subtract(amount);
            type = AdFlowTradeTypeEnum.SYSTEM_DEDUCT.getType();
        } else if (AdFlowTradeTypeEnum.USE.getTradeType().equals(tradeType)) {
            adPoint = user.getAdPoint().subtract(amount);
            type = AdFlowTradeTypeEnum.USE.getType();
        } else if (AdFlowTradeTypeEnum.SYSTEM_GIVING.getTradeType().equals(tradeType)) {
            adPoint = user.getAdPoint().add(amount);
            type = AdFlowTradeTypeEnum.SYSTEM_GIVING.getType();
        } else {
            return new BaseResp(ResultCode.FAIL);
        }

        userMapper.updateAdPointById(adPoint, userId);
        adFlowMapper.insert(AdFlow.builder()
                .userId(userId)
                .amount(amount)
                .tradeType(tradeType)
                .type(type)
                .adPoint(adPoint)
                .relateId(admin.getId())
                .createdAt(new Date())
                .build());

        return new BaseResp();
    }

    @Override
    public BaseResp editUserAgentLevel(UserAgentLevel req) {
        BaseResp baseResp = new BaseResp();
        User user = userMapper.findOneByUsername(req.getUserPhone());
        if (user == null) {
            return new BaseResp(ResultCode.USER_NOT_EXISTS);
        }

        UserAgentLevel old = userAgentLevelMapper.findOneByLocationIdAndExpireTime(req.getLocationId(), new Date());

        if (req.getId() == null) {
            if (old != null) {
                if (!old.getUserId().equals(user.getId())) {
                    //当前区域代理已存在且不为被添加人
                    baseResp = new BaseResp(ResultCode.FAIL);
                    baseResp.setMessage(req.getMergerName() + "已经有代理！");
                    return baseResp;
                } else {
                    //过期时间加一年
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(old.getExpireTime());
                    calendar.add(Calendar.YEAR, 1);
                    userAgentLevelMapper.updateExpireTimeById(calendar.getTime(), old.getId());

                    if (req.getFromUserId() != null) {
                        Identity identity = identityMapper.findOneByUserId(req.getFromUserId());
                        if (identity == null) {
                            return new BaseResp(ResultCode.GIVER_NOT_EXIST);
                        }
                        if (identity.getAreaAccount() <= 0) {
                            return new BaseResp(ResultCode.AREA_ACCOUNT_NOT_ENOUGH);
                        }
                        identityMapper.reduceAreaAccount(identity.getId());
                    }

                }
            } else {
                AreaApplyDetail areaApplyDetail = areaApplyDetailMapper.findOneByAreaAndStatus(req.getLocationId(), AreaApplyStatusEnum.WAIT_AUDIT.getStatus());
                if (areaApplyDetail != null) {
                    return new BaseResp(ResultCode.AREA_APPLY_WAIT_AUDIT);
                }

                //是否存在已过期区域代理
                UserAgentLevel oldUserAgentLevel = userAgentLevelMapper.findOneByLocationIdAndUserId(req.getLocationId(), user.getId());
                if (oldUserAgentLevel == null) {
                    req.setCreatedAt(new Date());
                    req.setUserId(user.getId());
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(new Date());
                    calendar.add(Calendar.YEAR, 1);
                    req.setExpireTime(calendar.getTime());
                    userAgentLevelMapper.insert(req);
                } else {
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(new Date());
                    calendar.add(Calendar.YEAR, 1);
                    userAgentLevelMapper.updateExpireTimeById(calendar.getTime(), oldUserAgentLevel.getId());
                }

                if (req.getFromUserId() != null) {
                    Identity identity = identityMapper.findOneByUserId(req.getFromUserId());
                    if (identity == null) {
                        return new BaseResp(ResultCode.GIVER_NOT_EXIST);
                    }
                    if (identity.getAreaAccount() <= 0) {
                        return new BaseResp(ResultCode.AREA_ACCOUNT_NOT_ENOUGH);
                    }
                    identityMapper.reduceAreaAccount(identity.getId());
                }
            }


        } else {
            if (old != null && !old.getId().equals(req.getId())) {
                baseResp = new BaseResp(ResultCode.FAIL);
                baseResp.setMessage(req.getMergerName() + "已经有代理！");
                return baseResp;
            }
            req.setUserId(user.getId());
            userAgentLevelMapper.updateByPrimaryKeySelective(req);
        }

        // 成为区域中心可获得兑换金额,发放嗨币
        BigDecimal cardPoint = user.getCardPoint().add(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig()));
        userMapper.updateCardPointById(cardPoint, user.getId());
        cardFlowMapper.insert(CardFlow.builder()
                .userId(user.getId())
                .amount(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig()))
                .tradeType(CardTradeTypeEnum.SYSTEM_GIVING.getTradeType())
                .type(CardTradeTypeEnum.SYSTEM_GIVING.getType())
                .cardPoint(cardPoint)
                .remark("赠送区域中心嗨币")
                .createdAt(new Date())
                .build());

        return baseResp;
    }

    @Override
    public BaseResp cancelUserAgentLevel(Long id) {
        UserAgentLevel userAgentLevel = userAgentLevelMapper.selectByPrimaryKey(id);

        userAgentLevelMapper.deleteByPrimaryKey(id);

        User user = userMapper.selectByPrimaryKey(userAgentLevel.getUserId());
        if (user.getCardPoint().compareTo(BigDecimal.ZERO) > 0) {
            cardFlowMapper.insert(CardFlow.builder()
                    .userId(userAgentLevel.getUserId())
                    .amount(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig()))
                    .tradeType(CardTradeTypeEnum.SYSTEM_DEDUCT.getTradeType())
                    .type(CardTradeTypeEnum.SYSTEM_DEDUCT.getType())
                    .cardPoint(user.getCardPoint().subtract(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig())))
                    .createdAt(new Date())
                    .build());
            userMapper.updateCardPointById(user.getCardPoint().subtract(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig())), userAgentLevel.getUserId());
        }

        // 其他已经发放的佣金，要自己扣除
        return new BaseResp();
    }

    @Override
    public ResultData<BasePageResp<UserAgentLevelVO>> getUserAgentLevelPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<UserAgentLevelVO> list = userAgentLevelMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(UserAgentLevelVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                if (userMap.get(item.getUserId()) != null) {
                    item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                    item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());

                }
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public void rankReward(Byte type) {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd  HH:mm:ss");
        int lastMonthMaxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        c.set(c.get(Calendar.YEAR), c.get(Calendar.MONTH), lastMonthMaxDay, 23, 59, 59);
        //上月最后一天
        String lastMonthEndTime = sdf.format(c.getTime());
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-01  00:00:00");
        String lastMonthStartTime = sdf2.format(c.getTime());

        List<RankNicknamePerformanceVO> list = userCommissionMapper.getRankByType(lastMonthStartTime, lastMonthEndTime);

        List<RankRecord> rankRecords = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, -1);


        if (!CollectionUtils.isEmpty(list)) {
            int len = list.size() > 3 ? 3 : list.size();
            for (int i = 0; i < len; i++) {
                rankRecords.add(RankRecord.builder()
                        .type(type)
                        .userId(list.get(i).getUserId())
                        .count(list.get(i).getTotalCount().intValue())
                        .rank(i + 1)
                        .date(getFirstTime(calendar).getTime())
                        .createdAt(new Date())
                        .build());
            }
        }

        if (!CollectionUtils.isEmpty(rankRecords)) {
            rankRecordMapper.batchInsert(rankRecords);

            //前三名发放奖励
            Long rewardCount = userCommissionMapper.getPartnerRewardCount(lastMonthStartTime, lastMonthEndTime);
            BigDecimal totalReward = new BigDecimal(rewardCount).multiply(new BigDecimal(daoService.getHipoConfigValue(HipoConfigEnum.TEACHER_CHAMPION_REWARD.getConfig()))).setScale(2, BigDecimal.ROUND_HALF_UP);
            List<Long> userIds = new ArrayList<>();
            userIds.add(list.get(0).getUserId());
            userIds.add(list.get(1).getUserId());
            userIds.add(list.get(2).getUserId());
            Map<Long, User> userMap = daoService.getUserMap(userIds);
            List<UserCommission> userCommissions = new ArrayList<>();
            List<BalanceFlow> balanceFlows = new ArrayList<>();
            BigDecimal firstReward = totalReward.multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP);
            BigDecimal secondReward = totalReward.multiply(new BigDecimal("0.3")).divide(new BigDecimal("2"), 2, BigDecimal.ROUND_HALF_DOWN);
            BigDecimal thirdReward = totalReward.multiply(new BigDecimal("0.5")).divide(new BigDecimal("3"), 2, BigDecimal.ROUND_HALF_DOWN);
            BigDecimal first = firstReward.add(secondReward).add(thirdReward);
            BigDecimal second = secondReward.add(thirdReward);
            BigDecimal third = thirdReward;
            Map<Long, BigDecimal> userRewardMap = new HashMap<>();
            userRewardMap.put(list.get(0).getUserId(), first);
            userRewardMap.put(list.get(1).getUserId(), second);
            userRewardMap.put(list.get(2).getUserId(), third);

            userRewardMap.forEach((key, value) -> {
                userCommissions.add(UserCommission.builder()
                        .superiorId(key)
                        .subordinateId(1L)
                        .commission(value)
                        .type(UserCommissionTypeEnum.PARTNER_RANK_REWARD.getType())
                        .status(UserCommissionStatusEnum.ISSUED.getStatus())
                        .createdAt(new Date())
                        .updatedAt(new Date())
                        .amount(BigDecimal.ZERO)
                        .identityType(IdentityTypeEnum.PARTNER.getType())
                        .businessType(BusinessTypeEnum.USER.getType())
                        .build());

                userMapper.changePointById(value, key);

                balanceFlows.add(BalanceFlow.builder()
                        .userId(key)
                        .amount(value)
                        .tradeType(TradeTypeEnum.PARTNER_RANK_REWARD.getTradeType())
                        .type(TradeTypeEnum.PARTNER_RANK_REWARD.getType())
                        .point(userMap.get(key).getPoint().add(value))
                        .createdAt(new Date())
                        .build());
            });
            userCommissionMapper.batchInsert(userCommissions);
            balanceFlowMapper.batchInsert(balanceFlows);
        }
    }

    private Calendar getFirstTime(Calendar calendar) {
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        return calendar;
    }

    @Override
    public ResultData<BasePageResp<TicketVO>> getTicketPage(TicketPageReq req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        req.setAdminId(admin.getId());
        List<TicketVO> list = ticketMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<Long> adminIds = list.stream().map(TicketVO::getAdminId).collect(Collectors.toList());
            adminIds.addAll(list.stream().map(TicketVO::getFirstAdminId).collect(Collectors.toList()));
            adminIds.addAll(list.stream().map(TicketVO::getSecondAdminId).collect(Collectors.toList()));
            Map<Long, Admin> adminMap = daoService.getAdminMap(adminIds);
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(TicketVO::getRelateId).collect(Collectors.toList()));
            Map<Long, Shop> shopMap = daoService.getShopMap(list.stream().map(TicketVO::getRelateId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                Admin applyAdmin = adminMap.get(item.getAdminId());
                item.setNickname(applyAdmin.getNickname());
                item.setAvatar(applyAdmin.getAvatar());
                item.setRealName(applyAdmin.getRealName());
                item.setFirstAvatar(adminMap.get(item.getFirstAdminId()).getAvatar());
                item.setFirstNickname(adminMap.get(item.getFirstAdminId()).getNickname());
                if (TicketLevelEnum.SECOND_AUDIT.getLevel().equals(item.getLevel())) {
                    item.setSecondAvatar(adminMap.get(item.getSecondAdminId()).getAvatar());
                    item.setSecondNickname(adminMap.get(item.getSecondAdminId()).getNickname());
                }
                if (TicketTypeEnum.EXCHANGE_BALANCE.getType().equals(item.getType()) || TicketTypeEnum.COMMISSION.getType().equals(item.getType())) {
                    if (userMap.containsKey(item.getRelateId())) {
                        item.setUserAvatar(userMap.get(item.getRelateId()).getAvatar());
                        item.setUserNickname(userMap.get(item.getRelateId()).getNickname());
                    }
                }
                if (TicketTypeEnum.TENANT.getType().equals(item.getType())) {
                    item.setTenantNickname(shopMap.get(item.getRelateId()).getShopName());
                }
                if (TicketTypeEnum.USER_LEVEL.getType().equals(item.getType())) {
                    VipReq vipReq = JSON.parseObject(item.getFeature(), VipReq.class);
                    User user = userMapper.findOneByUsername(vipReq.getPhone());
                    item.setUserAvatar(user.getAvatar());
                    item.setUserNickname(user.getNickname());
                }
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp editTicket(Ticket req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if (req.getId() == null) {
            if (!TicketTypeEnum.COMMON.getType().equals(req.getType()) && req.getRelateId() == null) {
                return new BaseResp(ResultCode.NEED_RELATE_ID);
            }
            req.setAdminId(admin.getId());
            req.setAuditStatus(TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus());
            req.setDeleted(DeletedEnum.DEFAULT.getStatus());
            req.setCreatedAt(new Date());
            req.setUpdatedAt(new Date());
            ticketMapper.insert(req);
        } else {
            Ticket ticket = ticketMapper.selectByPrimaryKey(req.getId());
            if (!ticket.getAdminId().equals(admin.getId())) {
                return new BaseResp(ResultCode.NOT_CREATE_ADMIN);
            }
            if (!TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus().equals(ticket.getAuditStatus())) {
                return new BaseResp(ResultCode.NOT_WAIT_AUDIT);
            }
            req.setUpdatedAt(new Date());
            req.setAuditStatus(TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus());
            ticketMapper.updateByPrimaryKeySelective(req);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp createUserLevelTicket(VipReq req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = userMapper.findOneByUsername(req.getPhone());
        if (user == null) {
            return new BaseResp(ResultCode.USER_NOT_EXISTS.getCode());
        }
        if (UserStatusEnum.BAN.getStatus().equals(user.getStatus())) {
            return new BaseResp(ResultCode.USER_BAN.getCode());
        }
        UserLevelEnum userLevelEnum = UserLevelEnum.getByLevel(req.getLevel());
        ticketMapper.insert(Ticket.builder()
                .adminId(admin.getId())
                .firstAdminId(HIPO_ADMIN_ID)
                .secondAdminId(HIPO_ADMIN_ID)
                .type(TicketTypeEnum.USER_LEVEL.getType())
                .level(TicketLevelEnum.SECOND_AUDIT.getLevel())
                .title("赠送身份" + userLevelEnum.getRemark() + "给手机号为：" + req.getPhone())
                .auditStatus(TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus())
                .deleted(DeletedEnum.DEFAULT.getStatus())
                .feature(JSON.toJSONString(req))
                .relateId(user.getId())
                .amount(BigDecimal.ZERO)
                .createdAt(new Date())
                .updatedAt(new Date())
                .build());
        return new BaseResp();
    }

    @Override
    public ResultData<TicketVO> getTicketDetail(Long id) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        TicketVO vo = new TicketVO();
        Ticket ticket = ticketMapper.selectByPrimaryKey(id);
        List<Long> adminIds = new ArrayList<>();
        adminIds.add(ticket.getAdminId());
        adminIds.add(ticket.getFirstAdminId());
        adminIds.add(ticket.getSecondAdminId());
        Map<Long, Admin> adminMap = daoService.getAdminMap(adminIds);
        if (ticket.getAdminId().equals(admin.getId()) || ticket.getFirstAdminId().equals(admin.getId()) || ticket.getSecondAdminId().equals(admin.getId())) {
            BeanUtils.copyProperties(ticket, vo);
            vo.setAvatar(adminMap.get(vo.getAdminId()).getAvatar());
            vo.setNickname(adminMap.get(vo.getAdminId()).getNickname());
            vo.setRealName(adminMap.get(vo.getAdminId()).getRealName());
            vo.setFirstAvatar(adminMap.get(vo.getFirstAdminId()).getAvatar());
            vo.setFirstNickname(adminMap.get(vo.getFirstAdminId()).getNickname());
            if (TicketLevelEnum.SECOND_AUDIT.getLevel().equals(vo.getLevel())) {
                vo.setSecondAvatar(adminMap.get(vo.getSecondAdminId()).getAvatar());
                vo.setSecondNickname(adminMap.get(vo.getSecondAdminId()).getNickname());
            }
            if (TicketTypeEnum.EXCHANGE_BALANCE.getType().equals(vo.getType()) || TicketTypeEnum.COMMISSION.getType().equals(vo.getType())) {
                User user = userMapper.selectByPrimaryKey(vo.getRelateId());
                vo.setUserAvatar(user.getAvatar());
                vo.setUserNickname(user.getNickname());
            }
            if (TicketTypeEnum.TENANT.getType().equals(vo.getType())) {
                Shop shop = shopMapper.selectByPrimaryKey(vo.getRelateId());
                vo.setTenantNickname(shop.getShopName());
            }
            return new ResultData<>(vo);
        }
        return new ResultData<>(null);
    }

    @Override
    public BaseResp deleteTicket(Long id) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Ticket ticket = ticketMapper.selectByPrimaryKey(id);
        if (ticket.getAdminId().equals(admin.getId())) {
            ticketMapper.updateDeletedById(DeletedEnum.DELETED.getStatus(), id);
        }
        return new BaseResp();
    }

    @Override
    public BaseResp firstAuditTicket(Ticket req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Ticket ticket = ticketMapper.selectByPrimaryKey(req.getId());
        if (!ticket.getFirstAdminId().equals(admin.getId())) {
            return new BaseResp(ResultCode.NOT_AUDIT_ADMIN);
        } else {
            if (!TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus().equals(ticket.getAuditStatus())) {
                return new BaseResp(ResultCode.AUDIT_FAIL);
            }
            if (TicketAuditStatusEnum.FIRST_PASS.getAduitStatus().equals(req.getAuditStatus()) || TicketAuditStatusEnum.FIRST_REJECT.getAduitStatus().equals(req.getAuditStatus())) {
                ticket.setAuditStatus(req.getAuditStatus());
                ticket.setFirstRemark(req.getFirstRemark());
                ticket.setFirstAuditTime(new Date());
                ticket.setUpdatedAt(new Date());
                ticketMapper.updateByPrimaryKey(ticket);

                if (TicketAuditStatusEnum.FIRST_PASS.getAduitStatus().equals(req.getAuditStatus())) {
                    isCompleteTicket(ticket);
                }
            }
        }
        return new BaseResp();
    }

    @Override
    public BaseResp secondAuditTicket(Ticket req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        Ticket ticket = ticketMapper.selectByPrimaryKey(req.getId());
        if (!ticket.getFirstAdminId().equals(admin.getId())) {
            return new BaseResp(ResultCode.NOT_AUDIT_ADMIN);
        } else {
            if (TicketAuditStatusEnum.WAIT_AUDIT.getAduitStatus().equals(ticket.getAuditStatus()) || TicketAuditStatusEnum.FIRST_REJECT.getAduitStatus().equals(ticket.getAuditStatus())) {
                return new BaseResp(ResultCode.FIRST_AUDIT_NOT_PASS);
            }
            if (!TicketAuditStatusEnum.FIRST_PASS.getAduitStatus().equals(ticket.getAuditStatus())) {
                return new BaseResp(ResultCode.AUDIT_FAIL);
            }
            if (!TicketLevelEnum.SECOND_AUDIT.getLevel().equals(ticket.getLevel())) {
                return new BaseResp(ResultCode.NOT_NEED_SECOND_AUDIT);
            }
            if (TicketAuditStatusEnum.SECOND_PASS.getAduitStatus().equals(req.getAuditStatus()) || TicketAuditStatusEnum.SECOND_REJECT.getAduitStatus().equals(req.getAuditStatus())) {
                ticket.setAuditStatus(req.getAuditStatus());
                ticket.setSecondRemark(req.getSecondRemark());
                ticket.setSecondAuditTime(new Date());
                ticket.setUpdatedAt(new Date());
                ticketMapper.updateByPrimaryKey(ticket);

                if (TicketAuditStatusEnum.SECOND_PASS.getAduitStatus().equals(req.getAuditStatus())) {
                    isCompleteTicket(ticket);
                }
            }
        }
        return new BaseResp();
    }

    private void isCompleteTicket(Ticket ticket) {
        if ((TicketAuditStatusEnum.FIRST_PASS.getAduitStatus().equals(ticket.getAuditStatus()) && TicketLevelEnum.FIRST_AUDIT.getLevel().equals(ticket.getLevel())) || (TicketAuditStatusEnum.SECOND_PASS.getAduitStatus().equals(ticket.getAuditStatus()) && TicketLevelEnum.SECOND_AUDIT.getLevel().equals(ticket.getLevel()))) {
            if (TicketTypeEnum.EXCHANGE_BALANCE.getType().equals(ticket.getType())) {
                userService.updateCardPoint(ticket.getRelateId(), ticket.getAmount());
            }
            if (TicketTypeEnum.COMMISSION.getType().equals(ticket.getType())) {
                fundService.issueCommissionDirect(ticket.getAmount(), ticket.getRelateId());
            }
            if (TicketTypeEnum.TENANT.getType().equals(ticket.getType())) {
                Tenant tenant = tenantMapper.selectByPrimaryKey(ticket.getRelateId());
                TenantTradeTypeEnum tenantTradeTypeEnum = ticket.getAmount().compareTo(BigDecimal.ZERO) >= 0 ? TenantTradeTypeEnum.SYSTEM_ADD : TenantTradeTypeEnum.SYSTEM_SUB;
                tenantFlowMapper.insert(TenantFlow.builder()
                        .amount(ticket.getAmount().abs())
                        .tradeType(tenantTradeTypeEnum.getTradeType())
                        .type(tenantTradeTypeEnum.getType())
                        .point(tenant.getPoint().add(ticket.getAmount()))
                        .relateId(ticket.getId())
                        .createdAt(new Date())
                        .tenantId(ticket.getRelateId())
                        .build());
                tenantMapper.updatePointById(tenant.getPoint().add(ticket.getAmount()), ticket.getRelateId());
            }

            //通过赠送身份审核
            if (TicketTypeEnum.USER_LEVEL.getType().equals(ticket.getType())) {
                vipService.createUserLevel(JSON.parseObject(ticket.getFeature(), VipReq.class));
            }
        }
    }

    @Override
    public ResultData<BasePageResp<AreaApplyVO>> getAreaApplyPage(AreaApplyPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<AreaApplyVO> list = areaApplyMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<AreaApplyDetail> areaApplyDetailList = areaApplyDetailMapper.findAllByAreaApplyIds(list.stream().map(AreaApplyVO::getId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(AreaApplyVO::getUserId).collect(Collectors.toList()));
            Map<Long, List<AreaApplyDetailVO>> areaApplyMap = new HashMap<>();
            List<Area> areaList = areaMapper.findAllbyIds(areaApplyDetailList.stream().map(AreaApplyDetail::getArea).collect(Collectors.toList()));
            Map<Long, Area> areaMap = new HashMap<>();
            areaList.stream().forEach(item -> {
                areaMap.put(item.getId(), item);
            });
            areaApplyDetailList.stream().forEach(item -> {
                List<AreaApplyDetailVO> newAreaApplyDetails = areaApplyMap.get(item.getAreaApplyId());
                if (newAreaApplyDetails == null) {
                    newAreaApplyDetails = new ArrayList<>();
                    AreaApplyDetailVO vo = new AreaApplyDetailVO();
                    BeanUtils.copyProperties(item, vo);
                    vo.setAreaName(areaMap.get(vo.getArea()).getName());
                    newAreaApplyDetails.add(vo);
                } else {
                    AreaApplyDetailVO vo = new AreaApplyDetailVO();
                    BeanUtils.copyProperties(item, vo);
                    vo.setAreaName(areaMap.get(vo.getArea()).getName());
                    newAreaApplyDetails.add(vo);
                }
                areaApplyMap.put(item.getAreaApplyId(), newAreaApplyDetails);
            });
            list.stream().forEach(item -> {
                item.setAreaApplyDetails(areaApplyMap.get(item.getId()));
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp auditAreaApply(AreaApply req) {
        Admin admin = (Admin) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        AreaApply areaApply = areaApplyMapper.selectByPrimaryKey(req.getId());
        if (!AreaApplyStatusEnum.WAIT_AUDIT.getStatus().equals(areaApply.getStatus())) {
            return new BaseResp(ResultCode.NOT_WAIT_AUDIT);
        }


        if (AreaApplyStatusEnum.PASS.getStatus().equals(req.getStatus())) {
            List<AreaApplyDetail> areaApplyDetails = areaApplyDetailMapper.findAllByAreaApplyId(req.getId());
            if (!CollectionUtils.isEmpty(areaApplyDetails)) {
                List<Area> areaList = areaMapper.findAllbyIds(areaApplyDetails.stream().map(AreaApplyDetail::getArea).collect(Collectors.toList()));
                Map<Long, Area> areaMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(areaList)) {
                    areaList.stream().forEach(item -> {
                        areaMap.put(item.getId(), item);
                    });
                }

                List<UserAgentLevel> userAgentLevelList = new ArrayList<>();
                List<UserAgentLevel> updateAgentLevelList = new ArrayList<>();
                User user = userMapper.selectByPrimaryKey(areaApply.getUserId());
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.YEAR, 1);


                List<UserAgentLevel> existUserAgentLevel = userAgentLevelMapper.findAllByLocationIdsAndUserId(areaApplyDetails.stream().map(AreaApplyDetail::getArea).collect(Collectors.toList()), user.getId());

                Map<Long, UserAgentLevel> existUserAgentLevelMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(existUserAgentLevel)) {
                    existUserAgentLevel.stream().forEach(item -> {
                        existUserAgentLevelMap.put(item.getLocationId(), item);
                    });
                }


                areaApplyDetails.stream().forEach(item -> {
                    UserAgentLevel userAgentLevel = existUserAgentLevelMap.get(item.getArea());
                    if (userAgentLevel != null) {
                        Calendar newExpireTime = Calendar.getInstance();
                        //未过期添加时间 过期后更新时间
                        if (userAgentLevel.getExpireTime().after(new Date())) {
                            newExpireTime.setTime(userAgentLevel.getExpireTime());
                        } else {
                            newExpireTime.setTime(new Date());
                        }
                        newExpireTime.add(Calendar.YEAR, 1);
                        userAgentLevel.setExpireTime(newExpireTime.getTime());
                        updateAgentLevelList.add(userAgentLevel);
                    } else {
                        userAgentLevelList.add(UserAgentLevel.builder()
                                .type(UserAgentLevelEnum.AREA.getType())
                                .locationId(item.getArea())
                                .mergerName(areaMap.get(item.getArea()).getMergerName())
                                .createdAt(new Date())
                                .userPhone(user.getUsername())
                                .userId(user.getId())
                                .expireTime(calendar.getTime())
                                .build());
                    }

                });
                if (!CollectionUtils.isEmpty(userAgentLevelList)) {
                    userAgentLevelMapper.batchInsert(userAgentLevelList);
                }
                if (!CollectionUtils.isEmpty(updateAgentLevelList)) {
                    userAgentLevelMapper.updateBatch(updateAgentLevelList);
                }
            }

            // 成为区域中心可获得兑换金额,发放嗨币
            User user = userMapper.selectByPrimaryKey(areaApply.getUserId());
            BigDecimal cardPoint = user.getCardPoint().add(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig()).multiply(new BigDecimal(areaApply.getAreaCount())));
            userMapper.updateCardPointById(cardPoint, user.getId());
            cardFlowMapper.insert(CardFlow.builder()
                    .userId(user.getId())
                    .amount(daoService.getHipoConfigNumber(HipoConfigEnum.AREA_EXCHANGE_AMOUNT.getConfig()).multiply(new BigDecimal(areaApply.getAreaCount())))
                    .tradeType(CardTradeTypeEnum.SYSTEM_GIVING.getTradeType())
                    .type(CardTradeTypeEnum.SYSTEM_GIVING.getType())
                    .cardPoint(cardPoint)
                    .remark("赠送区域中心嗨币")
                    .createdAt(new Date())
                    .build());

        }

        areaApplyMapper.updateStatusAndUpdatedAtAndAuditAdminIdById(req.getStatus(), new Date(), admin.getId(), req.getId());
        areaApplyDetailMapper.updateStatusAndUpdatedAtByAreaApplyId(req.getStatus(), new Date(), req.getId());
        return new BaseResp();
    }

    @Override
    public ResultData<AreaApplyVO> getAreaApplyDetail(Long id) {
        AreaApplyVO vo = new AreaApplyVO();
        AreaApply areaApply = areaApplyMapper.selectByPrimaryKey(id);
        BeanUtils.copyProperties(areaApply, vo);
        List<AreaApplyDetail> areaApplyDetails = areaApplyDetailMapper.findAllByAreaApplyId(id);
        List<AreaApplyDetailVO> voList = new ArrayList<>();
        List<Area> areaList = areaMapper.findAllbyIds(areaApplyDetails.stream().map(AreaApplyDetail::getArea).collect(Collectors.toList()));
        Map<Long, Area> areaMap = new HashMap<>();
        areaList.stream().forEach(item -> {
            areaMap.put(item.getId(), item);
        });
        areaApplyDetails.stream().forEach(item -> {
            AreaApplyDetailVO detailVO = new AreaApplyDetailVO();
            BeanUtils.copyProperties(item, detailVO);
            detailVO.setAreaName(areaMap.get(detailVO.getArea()).getName());
            voList.add(detailVO);
        });
        vo.setAreaApplyDetails(voList);
        return new ResultData<>(vo);
    }

    @Override
    public ResultData<BasePageResp<SuggestionVO>> getSuggestionPage(PageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<SuggestionVO> list = suggestionMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(SuggestionVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setNickname(userMap.get(item.getUserId()).getNickname());
                item.setAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setPhone(userMap.get(item.getUserId()).getUsername());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public BaseResp updateUserStaffType(Long id, Byte staffType) {
        userMapper.updateStaffTypeById(staffType, id);
        return new BaseResp();
    }

    @Override
    public ResultData<List<LongCountByDateVO>> getRegisterUserCount(CountByTimeReq req) {
        return new ResultData<>(userMapper.getRegisterUserCount(req));
    }

    @Override
    public BaseResp getGiveIdentityRecordPage(GiveIdentityRecordPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<GiveIdentityRecordVO> list = giveIdentityRecordMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            List<Long> userIdList = list.stream().map(GiveIdentityRecordVO::getToUserId).collect(Collectors.toList());
            userIdList.addAll(list.stream().map(GiveIdentityRecordVO::getFromUserId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(userIdList);
            list.stream().forEach(item -> {
                item.setToNickname(userMap.get(item.getToUserId()).getNickname());
                item.setToAvatar(userMap.get(item.getToUserId()).getAvatar());
                item.setFromNickname(userMap.get(item.getFromUserId()).getNickname());
                item.setFromAvatar(userMap.get(item.getFromUserId()).getAvatar());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<List<BankAccount>> getUserBankAccount(Long userId) {
        return new ResultData<>(bankAccountMapper.findAllByUserId(userId));
    }

    @Override
    public BaseResp editBankAccount(BankAccount bankAccount) {
        if (bankAccount.getId() == null) {
            bankAccount.setCreatedAt(new Date());
            bankAccount.setUpdatedAt(new Date());
            bankAccountMapper.insert(bankAccount);
        }
        return new BaseResp();
    }

    @Override
    public ResultData<MsgUser> getMsgUserDetail(Long userId) {
        return new ResultData<>(msgUserMapper.findOneByRelateIdAndRoleAndDeleted(userId, MsgUserRoleEnum.USER.getRole(), DeletedEnum.DEFAULT.getStatus()));
    }

    @Override
    public ResultData<BasePageResp<GroupsPerformanceVO>> getGroupsPerformancePage(GroupsPerformancePageReq req) {
        if (req.getDate() != null) {
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.setTime(req.getDate());
            Calendar endCalendar = Calendar.getInstance();
            endCalendar.setTime(req.getDate());
            req.setStartTime(getFirstTimeByTimeType(startCalendar, req.getTimeType()));
            req.setEndTime(getEndTimeByTimeType(endCalendar, req.getTimeType()));
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<GroupsPerformanceVO> list = groupsPerformanceMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, OrderSku> orderSkuMap = daoService.getOrderSkuMap(list.stream().map(GroupsPerformanceVO::getOrderSkuId).collect(Collectors.toList()));
            List<Long> userIds = orderSkuMap.values().stream().map(OrderSku::getUserId).collect(Collectors.toList());
            userIds.addAll(list.stream().map(GroupsPerformanceVO::getUserId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(userIds);
            list.stream().forEach(item -> {
                item.setToUserNickname(userMap.get(orderSkuMap.get(item.getOrderSkuId()).getUserId()).getNickname());
                item.setToUserAvatar(userMap.get(orderSkuMap.get(item.getOrderSkuId()).getUserId()).getAvatar());
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                OrderSku orderSku = orderSkuMap.get(item.getOrderSkuId());
                if (orderSku != null) {
                    item.setProductName(orderSku.getProductName());
                }
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<ShareholderPerformanceVO>> getShareholderPerformancePage(ShareholderPerformancePageReq req) {
        if (req.getDate() != null) {
            Calendar startCalendar = Calendar.getInstance();
            startCalendar.setTime(req.getDate());
            Calendar endCalendar = Calendar.getInstance();
            endCalendar.setTime(req.getDate());
            req.setStartTime(getFirstTimeByTimeType(startCalendar, req.getTimeType()));
            req.setEndTime(getEndTimeByTimeType(endCalendar, req.getTimeType()));
        }
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<ShareholderPerformanceVO> list = shareholderPerformanceMapper.findAllPage(req);
        if (!CollectionUtils.isEmpty(list)) {
            Map<Long, OrderSku> orderSkuMap = daoService.getOrderSkuMap(list.stream().map(ShareholderPerformanceVO::getOrderSkuId).collect(Collectors.toList()));
            List<Long> userIds = orderSkuMap.values().stream().map(OrderSku::getUserId).collect(Collectors.toList());
            userIds.addAll(list.stream().map(ShareholderPerformanceVO::getUserId).collect(Collectors.toList()));
            Map<Long, User> userMap = daoService.getUserMap(userIds);
            list.stream().forEach(item -> {
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setProductName((orderSkuMap.get(item.getOrderSkuId())).getProductName());
                item.setBuyUserAvatar(userMap.get(orderSkuMap.get(item.getOrderSkuId()).getUserId()).getAvatar());
                item.setBuyUserNickname(userMap.get(orderSkuMap.get(item.getOrderSkuId()).getUserId()).getNickname());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    private Date getFirstTimeByTimeType(Calendar calendar, Byte timeType) {
        if (timeType.equals(TimeType.DAY.getType())) {
            return getFirstTime(calendar).getTime();
        } else if (timeType.equals(TimeType.WEEK.getType())) {
            calendar.setFirstDayOfWeek(Calendar.MONDAY);
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            return getFirstTime(calendar).getTime();
        } else if (timeType.equals(TimeType.MONTH.getType())) {
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            return getFirstTime(calendar).getTime();
        } else {
            calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMinimum(Calendar.DAY_OF_YEAR));
            return getFirstTime(calendar).getTime();
        }
    }

    private Date getEndTimeByTimeType(Calendar calendar, Byte timeType) {
        if (timeType.equals(TimeType.DAY.getType())) {
            calendar.add(Calendar.DATE, +1);
            return getFirstTime(calendar).getTime();
        } else if (timeType.equals(TimeType.WEEK.getType())) {
            calendar.setFirstDayOfWeek(Calendar.MONDAY);
            calendar.add(Calendar.DATE, 7);
            calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
            return getFirstTime(calendar).getTime();
        } else if (timeType.equals(TimeType.MONTH.getType())) {
            calendar.add(Calendar.MONTH, +1);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            return getFirstTime(calendar).getTime();
        } else {
            calendar.add(Calendar.YEAR, +1);
            calendar.set(Calendar.DAY_OF_YEAR, calendar.getActualMinimum(Calendar.DAY_OF_YEAR));
            return getFirstTime(calendar).getTime();
        }
    }

    @Override
    public ResultData<BasePageResp<WelfareFlowVO>> getWelfareFlowPage(WelfareFlowPageReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<WelfareFlowVO> list = welfareFlowMapper.findAllPage(req);
        if (!list.isEmpty()) {
            Map<Long, User> userMap = daoService.getUserMap(list.stream().map(WelfareFlowVO::getUserId).collect(Collectors.toList()));
            list.stream().forEach(item -> {
                item.setUserAvatar(userMap.get(item.getUserId()).getAvatar());
                item.setUserNickname(userMap.get(item.getUserId()).getNickname());
            });
        }
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public ResultData<BasePageResp<UserCelebrityVo>> celebrityList(UserCelebrityReq req) {
        Page page = PageHelper.startPage(req.getPageNo(), req.getPageSize());
        List<UserCelebrityVo> list = userCelebrityMapper.celebrityList(req);
        return PageHelpUtil.buildPage(list, page);
    }

    @Override
    public void celebrityExamine(UserCelebrity celebrity) throws ResultCodeException {
        UserCelebrity userCelebrity = userCelebrityMapper.getById(celebrity.getId());
        if (userCelebrity == null) {
            return;
        }
        if (celebrity.getStatus().equals(UserCelebrityStatus.SECOND_REJECT.getCode())) {
            if (StringUtils.isEmpty(celebrity.getRemark())) {
                throw new ResultCodeException(ResultCode.REMARK_IS_NOT_NULL);
            }
            userCelebrityMapper.updateStatusById(celebrity.getId(), celebrity.getStatus(), celebrity.getRemark());
            return;
        }
        userCelebrityMapper.updateStatusById(celebrity.getId(), celebrity.getStatus(), null);
        User user = userMapper.selectByPrimaryKey(userCelebrity.getUserId());
        user.setLevel(5);
        userMapper.updateByPrimaryKey(user);
    }
}